//
// Abaondoned Mine adventure object handling
// 
// L. Dean Gibson II 3/8/01
//

// kill the 255+ character identifier warning.  Templates tend to exceed that easily.
#include "precompiled.h"
#pragma warning( disable: 4786 )


#include "adv_abandoned_mine.h"

#include <algorithm>

#include "abstract_script_action.h"
#include "adventure_ai.h"
#include "adventure_frame.h"
#include "adventure_map.h"
#include "adventure_sounds.h"
#include "ai_value.h"
#include "army.h"
#include "basic_dialog.h"
#include "combat_context_adv_object.h"
#include "combat_context_ptr.h"
#include "combat_result.h"
#include "creature.h"
#include "creature_type.h"
#include "format_string.h"
#include "enum_operations.h"
#include "estimate_outcome.h"
#include "hero_keyword_replacer.h"
#include "material_names.h"
#include "mine.h"
#include "mouse_event.h"
#include "music.h"
#include "object_registration.h"
#include "ownable_event.h"
#include "player.h"
#include "random.h"
#include "replace_keywords.h"
#include "run_combat.h"
#include "script_targeting.h"
#include "simple_dialog.h"

namespace
{
	int const k_current_map_version = 1;
	int const k_current_save_version = 4;

	t_object_registration<t_adv_abandoned_mine> registration( k_adv_object_abandoned_mine );

	// -------------------------------------------------------------------
	// Translate t_adv_abandoned_mine's save file version to t_creature_array's version
	// -------------------------------------------------------------------


};


// ------------------------------------------------------------------------
// fight creatures for a mine
// ------------------------------------------------------------------------
t_adv_abandoned_mine::t_adv_abandoned_mine( std::string const& source)
               : t_stationary_adventure_object( source )
{
	for ( int i = 0; i < k_garrison_scriptable_event_count; i++ )
	{
		m_built_in_events[i] = t_ownable_built_in_event_ptr( new t_ownable_built_in_event );
	}
}

// ------------------------------------------------------------------------
// Army approaches abandoned mine -- possible battle
// ------------------------------------------------------------------------
void t_adv_abandoned_mine::activate_trigger( t_army* army, t_adv_map_point const& point, 
		                                   t_direction direction, t_adventure_frame* frame )
{
	int player_number = army->get_owner_number();
	if (player_number == -1) 
		return;

	bool is_computer = army->get_owner()->is_computer();

	// note that this player has visited.
	if (player_number >= (int)m_visited.size())
		m_visited.insert( m_visited.end(), player_number - m_visited.size() + 1, false );
	m_visited[player_number] = true;

	if ( !t_creature_array::empty() )
	{
		if (!is_computer) 
		{
			t_counted_ptr<t_basic_dialog> dialog = new t_basic_dialog( frame );
			t_hero_keyword_replacer replacer;
			t_skill_mastery			information = get_information_level();

			replacer.add_creatures( *this, information < k_mastery_advanced );

			std::string text = replacer( get_text( "initial" ) );

			if (information >= k_mastery_expert)
				text += "  " + get_outcome_text( *this );

			dialog->set_text( text );
			dialog->add_creatures( *this, information < k_mastery_advanced );
			dialog->add_cancel_button();
			dialog->add_ok_button();
			dialog->set_title( get_name() );
			dialog->open( get_dialog_bottom(point), true, k_align_bottom );
			t_sound_cache music = get_music_playing();
			stop_music();
			get_dialog_sound( k_dialog_sound_abandoned )->play( get_sound_volume() );
			if (!dialog->run_modal())
				return;
			play_music( music );
		}

		execute_script(k_garrison_scriptable_begin_combat, army);

		// battle!
		t_combat_context_ptr	context;

		context = new t_combat_context_adv_object( army, this, get_position() );
		run_combat( *context );

		return;
	}
	
	execute_script(k_garrison_scriptable_lose_combat, army);

	visit( army, frame, *this );
}


void t_adv_abandoned_mine::on_combat_end( t_army* army, t_combat_result result, 
										  t_creature_array* losses,
										  t_adventure_frame* frame )
{
	frame->update_army( army );
		
	if (attacker_lost( result )) 
	{
		execute_script(k_garrison_scriptable_win_combat, army);
		return;
	}
	execute_script(k_garrison_scriptable_lose_combat, army);
	visit( army, frame, losses[true] );
}

void t_adv_abandoned_mine::visit( t_army* army, t_adventure_frame* frame, 
								  t_creature_array& losses )
{
	execute_script(k_garrison_scriptable_entered, army);
	frame->update_army(army);
	get_map()->process_continuous_events( frame );

	
	// player won, create a mine of appropriate type and place on this spot
	t_two_way_facing				  facing;
	t_adv_map_point					  obj_point;
	t_counted_ptr< t_mine >			  mine;
	t_adventure_map*				  map = frame->get_map();

	facing = (t_two_way_facing)get_minor_subtype();
	obj_point = get_position();

	// Just to make sure we don't do a "delete this" quite yet...
	t_counted_ptr< t_adv_abandoned_mine > this_holder = this;

	// destroy the abandoned mine
	destroy();

	// create a mine of the appropriate spot in its place
	mine = new t_mine( get_material(), facing );

	// copy the events across
	mine->copy_events( m_built_in_events, m_continuous_events, m_timed_events, m_triggerable_events );

	// place the mine where the abandoned mine was
	map = frame->get_map();
	mine->place(*map, obj_point);

	if (army->get_living_hero_count() == 0)
	{
		mine->set_owner( -1 );
		ok_dialog( mine->get_text( "no_heroes" ), true );
		return;
	}
	mine->set_owner( army->get_owner_number() );

	bool is_computer = army->get_owner()->is_computer();

	if (!is_computer)
	{
		// Run a dialog telling the player what they've won
		std::string text;
		std::string production;
		t_counted_ptr<t_basic_dialog> completion_dialog;
		production = format_string( "%i %s", mine->get_production(),
									get_material_name( get_material() ).c_str() );
		if ( losses.empty() )
		{
			text = replace_keywords( get_text( "initial_empty" ), 
									 "%material", production,
									 "%object_name", get_name() );
		}
		else
		{
			t_hero_keyword_replacer replacer;
			
			replacer.add_creatures( losses, true );
			replacer.add_keyword( "%material", production );

			text = replacer( get_text( "defeat" ) );
		}

		completion_dialog = new t_basic_dialog;
		completion_dialog->set_text( text );
		completion_dialog->set_title( get_name() );
		completion_dialog->add_ok_button();
		completion_dialog->add_material( get_material(), mine->get_production(), true, true );
		completion_dialog->open( get_dialog_bottom( army->get_position() ), true, k_align_bottom );
		t_sound_cache music = get_music_playing();
		stop_music();
		get_dialog_sound( k_dialog_sound_abandoned )->play( get_sound_volume() );
		completion_dialog->run_modal();
		play_music( music );
	}
}

// ------------------------------------------------------------------------
// Right click. If player has visited, s/he knows the creatures 
// guarding the mine
// ------------------------------------------------------------------------
void t_adv_abandoned_mine::right_click( t_mouse_event const& event,
								        t_adventure_frame* adventure_frame )
{
	bool		visited = false;
	int			player = get_map()->get_player_number();
	std::string text;
	t_skill_mastery information = get_information_level();

	if (information > k_mastery_none)
	{
		if (player >= (int)m_visited.size())
			m_visited.insert( m_visited.end(), player - m_visited.size() + 1, false );
		m_visited[player] = true;
	}

	if (player < (int)m_visited.size())
		visited = (m_visited[player]==0 ? false : true);

	if (!visited)
	{
		text = get_text( "help" );
	}
	else if (empty())
	{
		text = get_text( "help_empty" );
	}
	else
	{
		t_hero_keyword_replacer replacer;
		replacer.add_creatures( *this, information < k_mastery_advanced );

		text = replacer( get_text( "help_visited" ) );
		if (information >= k_mastery_expert)
			text += "  " + get_outcome_text( *this );
	}
	show_popup_text( text, event.screen_point );
}


// ------------------------------------------------------------------------
// Set up the default garrison
// ------------------------------------------------------------------------
void t_adv_abandoned_mine::default_garrison()
{
	// depending on type, set up an army to guard it
	t_creature_array::clear();

	switch (get_material())
	{
		case k_gold: 
			switch (random(1,4)) 
			{
				case 1: 
					t_creature_array::add(k_skeleton, random(100,120));
					t_creature_array::add(k_ghost, random(26,34));
					break;
				case 2: 
					t_creature_array::add(k_troglodyte, random(325,395));
					break;
				case 3:
					t_creature_array::add(k_troll, random(40,48));
					break;
				case 4:
					t_creature_array::add(k_gargoyle, random(58,70));
					break;
			}
			break;
		case k_wood: 
			switch (random(1,3)) 
			{
				case 1: 
					t_creature_array::add(k_skeleton, random(30,40));
					t_creature_array::add(k_ghost, random(5,7));
					break;
				case 2: 
					t_creature_array::add(k_bandit, random(55,75));
					break;
				case 3:
					t_creature_array::add(k_wolf, random(54,64));
					break;
			}
			break;
		case k_ore:	
			switch (random(1,4)) 
			{
				case 1: 
					t_creature_array::add(k_skeleton, random(30,40));
					t_creature_array::add(k_ghost, random(5,7));
					break;
				case 2: 
					t_creature_array::add(k_troglodyte, random(80,100));
					break;
				case 3:
					t_creature_array::add(k_troll, random(9,12));
					break;
				case 4:
					t_creature_array::add(k_gargoyle, random(14,18));
					break;
			}
			break;
		case k_crystal:
		case k_sulfur:
		case k_gems:
			switch (random(1,4)) 
			{
				case 1: 
					t_creature_array::add(k_skeleton, random(54,66));
					t_creature_array::add(k_ghost, random(12,16));
					break;
				case 2: 
					t_creature_array::add(k_troglodyte, random(160,200));
					break;
				case 3:
					t_creature_array::add(k_troll, random(20,24));
					break;
				case 4:
					t_creature_array::add(k_gargoyle, random(28,36));
					break;
			}
			break;
		case k_mercury:
			switch (random(1,3))
			{
				case 1: 
					t_creature_array::add(k_skeleton, random(54,66));
					t_creature_array::add(k_ghost, random(12,16));
					break;
				case 2: 
					t_creature_array::add(k_imp, random(225,275));
					break;
				case 3:
					t_creature_array::add(k_orc, random(110,140));
					break;
			}
			break;
	}

	assert( !t_creature_array::empty() );
}

// ------------------------------------------------------------------------
// Write to save file
// ------------------------------------------------------------------------
bool t_adv_abandoned_mine::write( std::streambuf& stream ) const
{
	if (    !t_creature_array::write( stream )
	     || !m_visited.write( stream ) )
	{
		return false;
	}

	return write_events( stream );
}

// ------------------------------------------------------------------------
// Write events to save file
// ------------------------------------------------------------------------
bool t_adv_abandoned_mine::write_events( std::streambuf& stream ) const
{
	put < t_uint16 >( stream, t_abstract_script_action::get_version() );

	t_garrison_scriptable_event event_id;
	for (	event_id = t_garrison_scriptable_event( 0 );
			event_id < k_garrison_scriptable_event_count;
			enum_incr( event_id ) )
	{
		if ( !m_built_in_events[ event_id ]->write( stream ) )
			return false;
	}
	
	int count = m_timed_events.size();
	put< t_uint16 >( stream, count );
	int i;
	for (i = 0; i < count; i++) {
		if (m_timed_events[i]->write( stream ) == false) 
			return false;
	}

	count = m_triggerable_events.size();
	put< t_uint16 >( stream, count );
	for (i = 0; i < count; i++) {
		if (m_triggerable_events[i]->write( stream ) == false) 
			return false;
	}

	count = m_continuous_events.size();
	put< t_uint16 >( stream, count );
	for (i = 0; i < count; i++) {
		if (m_continuous_events[i]->write( stream ) == false) 
			return false;
	}

	return true;
}

// ------------------------------------------------------------------------
// Save file version
// ------------------------------------------------------------------------
int t_adv_abandoned_mine::get_version() const
{
	return k_current_save_version;
}

// ------------------------------------------------------------------------
// Read from save file
// ------------------------------------------------------------------------
bool t_adv_abandoned_mine::read( std::streambuf&						stream, 
								 t_qualified_adv_object_type const&		type,
								 int									version )
{
	if ( version < 0 || version > k_current_save_version )
		return false;

	if ( version == 1 )
	{
		// Old material
		t_material old_material = get<t_material>( stream );

		if ( old_material != type.major_subtype() )
			return false;
	}

	if (version <= 2)
	{
		if (!read_version( stream, 0 ))
			return false;
	}
	else if (version < 4)
	{
		if (!read_version( stream, 1 ))
			return false;
	}
	else if (!t_creature_array::read( stream )) // version 4+ allow creature array its own version
		return false;

	if (version == 0)
	{
		get<t_uint8>( stream );
	}
	else
	{
		if ( !m_visited.read( stream ) )
			return false;
	}

	return read_events( stream, version );
}

// ------------------------------------------------------------------------
// Read all events from save file
// ------------------------------------------------------------------------
bool t_adv_abandoned_mine::read_events( std::streambuf& stream, int version )
{
	t_ownable_timed_event_list new_timed_events;
	t_ownable_triggerable_event_list new_triggerable_events;
	t_ownable_continuous_event_list new_continuous_events;
	
	if ( version >= 2 )
	{
		int scripting_version = get< t_uint16 >( stream );

		t_garrison_scriptable_event event_id;
		for (	event_id = t_garrison_scriptable_event( 0 );
				event_id < k_garrison_scriptable_event_count;
				enum_incr( event_id ) )
		{
			t_ownable_built_in_event_ptr new_event_ptr( new t_ownable_built_in_event );
			
			if ( !new_event_ptr->read( stream, scripting_version ) )
				return false;

			m_built_in_events[ event_id ] = new_event_ptr;
		}
				
		// Read the timed events
		int count = get< t_uint16 >( stream );
		new_timed_events.reserve( count );

		while ( count > 0 )
		{
			t_ownable_timed_event_ptr new_event_ptr( new t_ownable_timed_event );
			
			if ( !new_event_ptr->read( stream, scripting_version ) )
				return false;

			new_timed_events.push_back( new_event_ptr );

			--count;
		}

		// Read triggerable events
		count = get< t_uint16 >( stream );
		new_triggerable_events.reserve( count );

		while ( count > 0 )
		{
			t_ownable_triggerable_event_ptr new_event_ptr( new t_ownable_triggerable_event );
			if ( !new_event_ptr->read( stream, scripting_version ) )
				return false;

			new_triggerable_events.push_back( new_event_ptr );

			--count;
		}

		// Read continuous events
		count = get< t_uint16 >( stream );
		new_continuous_events.reserve( count );

		while ( count > 0 )
		{
			t_ownable_continuous_event_ptr new_event_ptr( new t_ownable_continuous_event );
			if ( !new_event_ptr->read( stream, scripting_version ) )
				return false;

			new_continuous_events.push_back( new_event_ptr );

			--count;
		}
	}

	m_timed_events.swap( new_timed_events );
	m_triggerable_events.swap( new_triggerable_events );
	m_continuous_events.swap( new_continuous_events );

	return true;
}

// ------------------------------------------------------------------------
// Read from map file
// ------------------------------------------------------------------------
bool t_adv_abandoned_mine::read_from_map( std::streambuf& stream, t_progress_handler* handler )
{
	t_uint16 format_version = get< t_uint16 >( stream );

	if ( format_version > k_current_map_version )
		return false;

	return    read_built_in_events_from_map( stream, format_version )
		   && read_continuous_events_from_map( stream, format_version )
		   && read_timed_events_from_map( stream, format_version )
		   && read_triggerable_events_from_map( stream, format_version )
		   && read_garrison_from_map( stream, format_version );
}

// ------------------------------------------------------------------------
// Read built in events from map file
// ------------------------------------------------------------------------
bool t_adv_abandoned_mine::read_built_in_events_from_map( std::streambuf& stream, t_uint16 format_version )
{
	if ( format_version == 0 )
		return true;

	int i;

	for ( i = 0; i < k_garrison_scriptable_event_count; i++ )
	{
		if ( !m_built_in_events[i]->read_from_map( stream ) )
			return false;
	}

	return true;
}

// ------------------------------------------------------------------------
// Read continuous events from map file
// ------------------------------------------------------------------------
bool t_adv_abandoned_mine::read_continuous_events_from_map( std::streambuf& stream, t_uint16 format_version )
{
	m_continuous_events.clear();

	if ( format_version == 0 )
		return true;

	t_uint16 count = get< t_uint16 >( stream );

	m_continuous_events.reserve( count );

	while ( count ) 
	{
		t_ownable_continuous_event_ptr event_ptr( new t_ownable_continuous_event );
		
		if ( !event_ptr->read_from_map( stream ) )
			return false;

		m_continuous_events.push_back( event_ptr );

		count--;
	}

	return true;
}

// ------------------------------------------------------------------------
// Read the initial garrison from map file, or default
// ------------------------------------------------------------------------
bool t_adv_abandoned_mine::read_garrison_from_map( std::streambuf& stream, t_uint16 format_version )
{
	bool custom_garrison;

	if ( format_version == 0 )
		custom_garrison = false;
	else
		custom_garrison = ( get< t_uint8 >( stream ) != 0 );

	if ( custom_garrison )
	{
		if ( !t_creature_array::read_from_map( stream ) )
			return false;
	}
	else
	{
		default_garrison();
	}

	return true;
}

// ------------------------------------------------------------------------
// Read the timed events from map file
// ------------------------------------------------------------------------
bool t_adv_abandoned_mine::read_timed_events_from_map( std::streambuf& stream, t_uint16 format_version )
{
	m_timed_events.clear();

	if ( format_version == 0 )
		return true;

	t_uint16 count = get< t_uint16 >( stream );

	m_timed_events.reserve( count );

	while ( count ) 
	{
		t_ownable_timed_event_ptr event_ptr( new t_ownable_timed_event );
		
		if ( !event_ptr->read_from_map( stream ) )
			return false;

		m_timed_events.push_back( event_ptr );

		count--;
	}

	return true;
}

// ------------------------------------------------------------------------
// Read the triggerable events from map file
// ------------------------------------------------------------------------
bool t_adv_abandoned_mine::read_triggerable_events_from_map( std::streambuf& stream, t_uint16 format_version )
{
	m_triggerable_events.clear();

	if ( format_version == 0 )
		return true;

	t_uint16 count = get< t_uint16 >( stream );

	m_triggerable_events.reserve( count );

	while ( count ) 
	{
		t_ownable_triggerable_event_ptr event_ptr( new t_ownable_triggerable_event );
		
		if ( !event_ptr->read_from_map( stream ) )
			return false;

		m_triggerable_events.push_back( event_ptr );

		count--;
	}

	return true;
}

// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
float t_adv_abandoned_mine::ai_value( t_adventure_ai const& ai, t_creature_array const& army, int move_cost ) const
{
	t_player* player = army.get_owner();

	if (army.get_living_hero_count() == 0)
		return 0.0f;

	float value_drop = value_lost_in_combat(&army, this);
	float actual_value_drop = army.ai_value() * value_drop;

	if (value_drop >= k_lost_value_death_threshold)
		return 0.0f;

	float mine_value = 
			(player->get_material_value(get_material()) 
			* get_mine_production(get_material()) 
			* k_ai_mine_value_multiplier)
			- actual_value_drop;

	return mine_value;
}



// -------------------------------------------------------------------
// Pass various notifications to the garrison
// -------------------------------------------------------------------
bool t_adv_abandoned_mine::preplacement( t_adventure_map& map, int pass )
{
	bool result_base = t_stationary_adventure_object::preplacement( map, pass );
	bool result_garrison = t_creature_array::preplacement( map, pass, NULL );

	return result_base || result_garrison;
}

// ---------------------------------------------------------------
// Called after read()
// ---------------------------------------------------------------
void t_adv_abandoned_mine::read_postplacement( t_adventure_map& map )
{
	t_stationary_adventure_object::read_postplacement( map );
	t_creature_array::read_postplacement( map );
}

// ---------------------------------------------------------------
// Called after read_from_map()
// ---------------------------------------------------------------
void t_adv_abandoned_mine::initialize( t_adventure_map& map )
{
	t_stationary_adventure_object::initialize( map );
	t_creature_array::initialize();
}

// ---------------------------------------------------------------
// ---------------------------------------------------------------
void t_adv_abandoned_mine::place( t_adventure_map& map, t_adv_map_point const& point )
{
	t_stationary_adventure_object::place( map, point );

    int max;
    if (get_material() == k_gold)
        max = 1000;
    else
        max = 500;
    map.add_to_total_income ( max );
}

// ------------------------------------------------------------------------
// Process a new day. Abandoned mines' guards grow much like wandering 
// monsters do.
// ------------------------------------------------------------------------
void t_adv_abandoned_mine::process_new_day()
{
	t_creature_array::process_new_day( true );
	t_stationary_adventure_object::process_new_day();
}

// ---------------------------------------------------------------
// ---------------------------------------------------------------
void t_adv_abandoned_mine::execute_script(t_garrison_scriptable_event event_id, t_army* army)
{
	assert( event_id >= 0 && event_id < k_garrison_scriptable_event_count );
	assert( army != 0 );

	t_ownable_built_in_event_ptr & event_ptr = m_built_in_events[ event_id ];

	if (!event_ptr->ownership_test(get_owner())) return;

	t_adventure_frame* frame = get_adventure_frame();
	event_ptr->execute_effects(get_map()->get_current_player(), frame);
	frame->update();

	t_ownable_built_in_event::t_script const & script = event_ptr->get_script();
	script.execute( t_script_context_town( get_map(), NULL, this, army, army->get_owner(), &army->get_position() ) );
	if (get_map()->is_game_over())
		return;

	frame->update();
	post_execute_validate(this);
	post_execute_validate(army);
		
	if ( script.pending_removal() ) {
		script.clear_removal();
		event_ptr = new t_ownable_built_in_event;
	}

	get_map()->process_continuous_events( frame );
	frame->update();
}

// -----------------------------------------------------------
// -----------------------------------------------------------
bool t_adv_abandoned_mine::process_timed_events( t_adventure_map& map, bool start_of_day )
{
	bool result = false;

	int size = m_timed_events.size();
	for (int i = 0; i < size; i++) {
		t_ownable_timed_event_ptr& event = m_timed_events[i];
		if ( event->is_active_on_day(map.get_day()) 
			&& (&map.get_current_player() == get_owner())
			&& event->ownership_test(get_owner())
			&& (start_of_day || !event->has_executed()) )
		{
			result = true;

			event->set_execution_flag();
			event->execute_effects(map.get_current_player(), get_adventure_frame());
			get_adventure_frame()->update();

			t_timed_event::t_script const & script = event->get_script();
			script.execute(t_script_context_town(&map, NULL, this, NULL, NULL, &get_position()));
			if (map.is_game_over())
				return false;
			
			get_adventure_frame()->update();
			post_execute_validate(this);

			if (script.pending_removal()) {
				script.clear_removal();
				event = new t_ownable_timed_event;
			}
		}
		else
			if (start_of_day)
				event->clear_execution_flag();
	}

	return result;
}

// -----------------------------------------------------------
// -----------------------------------------------------------
bool t_adv_abandoned_mine::process_continuous_events( t_adventure_map& map )
{
	bool result = false;

	int size = m_continuous_events.size();
	for (int i = 0; i < size; i++) {
		t_ownable_continuous_event_ptr & event = m_continuous_events[i];
		if (( !event->get_run_only_during_owners_turn() || &map.get_current_player() == get_owner() )
			&& event->ownership_test(get_owner()) )
		{
			result = true;

			t_continuous_event::t_script const & script = event->get_script();
			script.execute(t_script_context_town(&map, NULL, this, NULL, NULL, &get_position()));
			if (map.is_game_over())
				return false;

			get_adventure_frame()->update();
			post_execute_validate(this);

			if (script.pending_removal()) {
				script.clear_removal();
				event = new t_ownable_continuous_event;
			}
		}
	}

	return result;
}

// -----------------------------------------------------------
// -----------------------------------------------------------
bool t_adv_abandoned_mine::process_triggerable_events( t_adventure_map& map, std::string const& name )
{
	bool result = false;

	int size = m_triggerable_events.size();
	for (int i = 0; i < size; i++) {
		t_ownable_triggerable_event_ptr & event = m_triggerable_events[i];
		if (( string_insensitive_compare(event->get_name(), name) == 0 )
			&& event->ownership_test(get_owner()) )
		{
			result = true;

			event->execute_effects(map.get_current_player(), get_adventure_frame());
			get_adventure_frame()->update();
			
			t_triggerable_event::t_script const & script = event->get_script();
			script.execute(t_script_context_town(&map, NULL, this, NULL, NULL, &get_position()));
			if (map.is_game_over())
				return false;

			get_adventure_frame()->update();
			post_execute_validate(this);

			if (script.pending_removal()) {
				script.clear_removal();
				event = new t_ownable_triggerable_event;
			}
		}
	}

	return result;
}

// -----------------------------------------------------------
// -----------------------------------------------------------
void t_adv_abandoned_mine::on_begin_turn()
{
	t_creature_array::on_begin_turn();
	t_stationary_adventure_object::on_begin_turn();
}

// -----------------------------------------------------------
// -----------------------------------------------------------
void t_adv_abandoned_mine::on_end_turn()
{
	t_creature_array::on_end_turn();
	t_stationary_adventure_object::on_end_turn();
}

// -----------------------------------------------------------
// -----------------------------------------------------------
float t_adv_abandoned_mine::ai_activation_value_drop( t_creature_array const& army ) const
{
	return ::value_lost_in_combat( &army, this );
}

// -----------------------------------------------------------
// -----------------------------------------------------------
t_skill_mastery t_adv_abandoned_mine::get_anti_stealth_level() const
{
	return t_creature_array::get_anti_stealth_level();
}
